using System;
using System.Linq;
using System.Web.Mvc;
using OurWedding1.Models;
using System.IO;
using OurWedding1.IO;

namespace OurWedding1.Controllers
{
    //[Authorize(Roles = "User")]
    [Authorize]
    public class GuestsController : BaseController
    {
        private readonly IWeddingRepository _weddingRepository;
        private readonly IGuestGroupRepository _guestgroupRepository;
        private readonly IGuestFunctionRepository _guestfunctionRepository;
        private readonly IGuestRepository _guestRepository;

        // If you are using Dependency Injection, you can delete the following constructor
        public GuestsController()
            : this(new WeddingRepository(), new GuestGroupRepository(), new GuestFunctionRepository(), new GuestRepository())
        {
        }

        private IQueryable<GuestFunction> GetPossibleGuestFunctions(GuestSide side)
        {
            return _guestfunctionRepository.All.Where(f => f.GuestSideId == side.GuestSideId).OrderBy(f=>f.Name);
        }

        public GuestsController(IWeddingRepository weddingRepository, IGuestGroupRepository guestgroupRepository, IGuestFunctionRepository guestfunctionRepository, IGuestRepository guestRepository)
        {
            _weddingRepository = weddingRepository;
            _guestgroupRepository = guestgroupRepository;
            _guestfunctionRepository = guestfunctionRepository;
            _guestRepository = guestRepository;
        }

        //
        // GET: /Guests/

        public ActionResult Index()
        {

            var selectedWedding = SelectedWeddingId;
            if (!selectedWedding.HasValue)
            {
                return RedirectToAction("Index", "Weddings");
            }

            var model = _guestRepository.AllIncluding(guest => guest.GuestGroup, guest => guest.GuestFunction, guest => guest.Installments, guest => guest.Tasks, guest => guest.GuestInExpenses).Where(g => g.WeddingId == selectedWedding.Value);
            ViewBag.Count = model.Count();
            return View(model);
        }

        public ActionResult IndexAjax()
        {
            var selectedWedding = SelectedWeddingId;
            if (!selectedWedding.HasValue)
            {
                Content(""); //TODO:Error
            }
            var model = _guestRepository.AllIncluding(guest => guest.GuestGroup, guest => guest.GuestFunction, guest => guest.Installments, guest => guest.Tasks, guest => guest.GuestInExpenses).Where(g => g.WeddingId == selectedWedding.Value);
            //model = model.OrderBy(g => g.GuestFunction.Priority).ThenByDescending(g => g.GuestGroup.GuestSideId).ThenBy(g => g.GuestGroup.Name); //TODO:Improve
            return PartialView("_Index", model);
        }

        public ActionResult SummaryAjax()
        {
            if (!SelectedWeddingId.HasValue)
            {
                return Content("");
            }
            var guests = _guestRepository.AllIncluding(guest => guest.GuestGroup, guest => guest.GuestFunction, guest => guest.Installments, guest => guest.Tasks, guest => guest.GuestInExpenses).Where(g => g.WeddingId == SelectedWeddingId.Value);
            var model = new GuestSummaryViewModel
                {
                    GuestsBrideAmount = guests.Count(g => g.GuestGroup.GuestSide.IsBrideSide),
                    GuestsAmount = guests.Count(),
                    GuestsGroomAmount = guests.Count(g => g.GuestGroup.GuestSide.IsGroomSide),
                    GuestsCommonAmount = guests.Count(g=>g.GuestGroup.GuestSide.isCommonSide),
                    GuestsInHotelAmount = guests.Count(g => g.isHotelNeeded),
                    GuestsNotIncludedAmount = guests.Count(g => g.isNotIncluded),
                    GuestsConfirmedAmount = guests.Count(g => g.isConfirmed)
                };
            return PartialView("_Summary", model);
        }

        public PartialViewResult IndexByGuestGroup(int id)
        {
            GuestGroup group = _guestgroupRepository.Find(id);
            if (group == null)
            {
                return null;
            }

            var model = _guestRepository.AllIncluding(guest => guest.GuestGroup, guest => guest.GuestFunction, guest => guest.Installments, guest => guest.Tasks, guest => guest.GuestInExpenses).Where(g => g.GuestGroupId == group.GuestGroupId);
            model = model.OrderBy(g => g.GuestFunction.GuestSideId);
            return PartialView("_IndexByGuestGroup", model);
        }

        public ActionResult CreateByGuestGroup(int id)
        {
            var group = _guestgroupRepository.Find(id);
            if (!SelectedWeddingId.HasValue || group == null)
            {
                return Content(""); //TODO:Error Introduce
            }
            if (group.WeddingId != SelectedWeddingId)
            {
                return Content(""); //TODO:Error Introduce
            }
            var model = new Guest {GuestGroupId = @group.GuestGroupId, WeddingId = SelectedWeddingId};
            ViewBag.PossibleGuestFunctions = GetPossibleGuestFunctions(group.GuestSide);
            return PartialView("_CreateByGuestGroup", model);
        }

        //
        // POST: /Guests/Create

        [HttpPost]
        public ActionResult CreateByGuestGroup(int id, Guest model)
        {
            var group = _guestgroupRepository.Find(id);
            if (!SelectedWeddingId.HasValue || group == null)
            {
                return Content(""); //TODO:Error Introduce
            }
            if (ModelState.IsValid)
            {
                _guestRepository.InsertOrUpdate(model);
                bool succeded;
                try
                {
                    _guestRepository.Save();
                    succeded = true;
                }
                catch (Exception)
                {
                    succeded = false;
                }

                if (succeded)
                {
                    return Json(new
                    {
                        value = "K!"
                    });
                }

                ModelState.AddModelError("a", Resources.ErrorOcured);
            }
            ViewBag.PossibleGuestFunctions = GetPossibleGuestFunctions(group.GuestSide);

            return PartialView("_CreateByGuestGroup", model);
        }

        public ActionResult EditByGuestGroup(int id)
        {
            var model = _guestRepository.Find(id);
            if (!SelectedWeddingId.HasValue || model == null)
            {
                return Content(""); //TODO:Error introduce
            }
            if (model.GuestGroup.WeddingId != SelectedWeddingId)
            {
                return Content(""); //TODO:Error introduce
            }
            ViewBag.PossibleGuestFunctions = GetPossibleGuestFunctions(model.GuestGroup.GuestSide);
            return PartialView("_EditByGuestGroup", model);
        }

        [HttpPost]
        public ActionResult EditByGuestGroup(Guest model)
        {
            if (ModelState.IsValid)
            {
                // validation of the modal view model succeeded =>
                // we return a JSON result containing some precalculated value
                _guestRepository.InsertOrUpdate(model);
                bool succeded;
                try
                {
                    _guestRepository.Save();
                    succeded = true;
                }
                catch (Exception)
                {
                    succeded = false;
                }

                if (succeded)
                {
                    return Json(new
                    {
                        value = "K!"
                    });
                }
                ModelState.AddModelError("a", Resources.ErrorOcured);

            }
            // Validation failed => we need to redisplay the modal form
            // and give the user the possibility to fix his errors
            ViewBag.PossibleGuestFunctions = GetPossibleGuestFunctions(model.GuestGroup.GuestSide);
            return PartialView("_EditByGuestGroup", model);
        }

        [HttpPost]
        public ActionResult DeleteAjax(int id)
        {
            var model = _guestRepository.Find(id);
            if (!SelectedWeddingId.HasValue || model == null)
            {
                return Json(new
                {
                    value = "nok"
                });
            }
            if (model.GuestGroup.WeddingId != SelectedWeddingId.Value)
            {
                return Json(new
                {
                    value = "nok"
                });
            }
            _guestRepository.Delete(id);
            bool succeded;
            try
            {
                _guestRepository.Save();
                succeded = true;
            }
            catch (Exception)
            {
                succeded = false;
            }

            if (succeded)
            {
                return Json(new
                {
                    value = "ok"
                });
            }
            return Json(new
            {
                value = "nok"
            });
        }
        
        public ActionResult ExcelReport()
        {
            if (!SelectedWeddingId.HasValue)
            {
                return RedirectToAction("Index", "Weddings");
            }
            var memoryStream = new MemoryStream();

            var model = _guestRepository.All.Where(g => g.GuestGroup.WeddingId == SelectedWeddingId.Value).ToList();

            var renderer = new GuestsExcellRenderer {Rows = model};

            renderer.Render(memoryStream);

            return File(memoryStream.GetBuffer(), "application/vnd.ms-excel");

        }


        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                _weddingRepository.Dispose();
                _guestgroupRepository.Dispose();
                _guestfunctionRepository.Dispose();
                _guestRepository.Dispose();
            }
            base.Dispose(disposing);
        }
    }
}

